package com.zxp.utils.configParseUtils;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class JsonConfigReader {

    private static final String CONFIG_FILE = "config.json";

    private static JsonNode config;

    static {
        loadConfig();
    }
    /**
     * Load the config file into a JsonNode object.
     */
    private static void loadConfig() {
        ObjectMapper objectMapper = new ObjectMapper();
        try (InputStream input = JsonConfigReader.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) {
            if (input == null) {
                throw new RuntimeException("Unable to find " + CONFIG_FILE);
            }

            // parse JSON file into a JsonNode
            config = objectMapper.readTree(input);

        } catch (IOException e) {
            throw new RuntimeException("Error loading " + CONFIG_FILE, e);
        }
    }
    /**
     * Get the value for a specified key.
     *
     * @param key The key to get the value for
     * @return The value for the specified key
     */

    public static String getString(String key) {
        String[] keyParts = key.split("\\.");

        JsonNode currentNode = config;
        for (String part : keyParts) {
            currentNode = currentNode.get(part);

            if (currentNode == null) {
                throw new RuntimeException("Config key '" + key + "' not found in " + CONFIG_FILE);
            }
        }

        if (currentNode.isTextual()) {
            return currentNode.asText();
        } else {
            throw new RuntimeException("Config key '" + key + "' is not a text value in " + CONFIG_FILE);
        }
    }
    /**
     * Get the value of a specified key.
     *
     * @param key The key to get the value for
     * @return The value of the specified key
     */
    public static int getInt(String key) {
        String[] keyParts = key.split("\\.");

        JsonNode currentNode = config;
        for (String part : keyParts) {
            currentNode = currentNode.get(part);

            if (currentNode == null) {
                throw new RuntimeException("Config key '" + key + "' not found in " + CONFIG_FILE);
            }
        }

        if (currentNode.isInt()) {
            return currentNode.asInt();
        } else {
            throw new RuntimeException("Config key '" + key + "' is not an integer value in " + CONFIG_FILE);
        }
    }

    public static boolean getBoolean(String key) {
        String[] keyParts = key.split("\\.");

        JsonNode currentNode = config;
        for (String part : keyParts) {
            currentNode = currentNode.get(part);

            if (currentNode == null) {
                throw new RuntimeException("Config key '" + key + "' not found in " + CONFIG_FILE);
            }
        }

        if (currentNode.isBoolean()) {
            return currentNode.asBoolean();
        } else {
            throw new RuntimeException("Config key '" + key + "' is not a boolean value in " + CONFIG_FILE);
        }
    }
    /**
     * Read the list of all child keys under a specified parent key.
     *
     * @param parentKey Parent key name
     * @return List containing all child key names
     */
    public static List<String> getAllKeysUnderKey(String parentKey) {
        List<String> keysList = new ArrayList<>();

        ObjectMapper objectMapper = new ObjectMapper();

        try (InputStream input = JsonConfigReader.class.getClassLoader().getResourceAsStream(CONFIG_FILE)) {
            if (input == null) {
                throw new RuntimeException("Unable to find " + CONFIG_FILE);
            }

            // parse JSON file into a JsonNode
            JsonNode config = objectMapper.readTree(input);

            // get the nested node under the parent key
            JsonNode parentNode = getConfigNode(config, parentKey);

            // extract all keys under the parent key
            if (parentNode != null) {
                Iterator<String> fieldNames = parentNode.fieldNames();
                while (fieldNames.hasNext()) {
                    keysList.add(fieldNames.next());
                }
            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return keysList;
    }
    /**
     * Get the JsonNode object for a specified key.
     *
     * @param config The JsonNode object representing the config file
     * @param key    The key to get the JsonNode object for
     * @return The JsonNode object for the specified key
     */
    private static JsonNode getConfigNode(JsonNode config, String key) {
        String[] keyParts = key.split("\\.");

        JsonNode currentNode = config;

        for (String part : keyParts) {
            currentNode = currentNode.get(part);

            if (currentNode == null) {
                // The key is not nested as expected
                return null;
            }
        }

        return currentNode;
    }
    public static void main(String[] args) {
        // Example usage:
//        String databaseUrl = getString("database.url");
//        String username = getString("database.username");
//        String password = getString("database.password");
//        System.out.println(getString("database.driver.name"));
//        System.out.println("Database URL: " + databaseUrl);
//        System.out.println("Username: " + username);
//        System.out.println("Password: " + password);
        System.out.println("=========================");
        String parentKey = "jdk"; // Replace with your desired parent key
        List<String> keysUnderParentKey = getAllKeysUnderKey(parentKey);
        System.out.println("Keys under " + parentKey + ": " + keysUnderParentKey);
        String string = getString("jdk.21.0.2");
        System.out.println(string);
        // Example output:

    }
}
